<!DOCTYPE html><html lang="zh-CN" data-theme="dark"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>面向对象 | 北城韩雨</title><meta name="keywords" content="JS高级"><meta name="author" content="北城韩雨"><meta name="copyright" content="北城韩雨"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#0d0d0d"><meta name="description" content="JS高级">
<meta property="og:type" content="article">
<meta property="og:title" content="面向对象">
<meta property="og:url" content="http://example.com/2019/03/28/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/index.html">
<meta property="og:site_name" content="北城韩雨">
<meta property="og:description" content="JS高级">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2018-07-17%2Faf41dabad727ba80c9ca8a2bfbd22a58%2F00004.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&refer=http%3A%2F%2Fpic.vjshi.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1629530659&t=bbcfe1e86f393eecbb0722db1b92e475">
<meta property="article:published_time" content="2019-03-27T16:00:00.000Z">
<meta property="article:modified_time" content="2019-06-02T16:00:00.000Z">
<meta property="article:author" content="北城韩雨">
<meta property="article:tag" content="JavaScript">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2018-07-17%2Faf41dabad727ba80c9ca8a2bfbd22a58%2F00004.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&refer=http%3A%2F%2Fpic.vjshi.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1629530659&t=bbcfe1e86f393eecbb0722db1b92e475"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://example.com/2019/03/28/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'mediumZoom',
  Snackbar: undefined,
  source: {
    jQuery: 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isanchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: '面向对象',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2019-06-03 00:00:00'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
    const detectApple = () => {
      if (GLOBAL_CONFIG_SITE.isHome && /iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><link rel="stylesheet" href="/css/custom.css"  media="defer" onload="this.media='all'"><link rel="stylesheet" href="/css/coin.css"  media="defer" onload="this.media='all'"><link rel="stylesheet" href="/css/liuxing.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/l-lin/font-awesome-animation/dist/font-awesome-animation.min.css"  media="defer" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper/swiper-bundle.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/zhheo/JS-Heo@main/bb/showbb_in_index.css"><!-- hexo injector head_end start --><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" media="print" onload="this.media='screen'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/l-lin/font-awesome-animation/dist/font-awesome-animation.min.css" media="defer" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-butterfly-tag-plugins-plus/lib/tag_plugins.min.css" media="defer" onload="this.media='all'"><!-- hexo injector head_end end --><meta name="generator" content="Hexo 5.3.0"></head><body><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="/img/my.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/archives/"><div class="headline">文章</div><div class="length-num">65</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/tags/"><div class="headline">标签</div><div class="length-num">23</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/categories/"><div class="headline">分类</div><div class="length-num">21</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/"><i class="fa-fw fas fa-home faa-tada"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/shuoshuo/"><i class="fa-fw fas fa-archive faa-tada"></i><span> 叨逼叨</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/tags/"><i class="fa-fw fas fa-tags faa-tada"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/categories/"><i class="fa-fw fas fa-folder-open faa-tada"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/link/"><i class="fa-fw fas fa-link faa-tada"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/comments/"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-message"></use></svg><span> 留言板</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/about/"><i class="fa-fw fas fa-heart faa-tada"></i><span> 个人简介</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2018-07-17%2Faf41dabad727ba80c9ca8a2bfbd22a58%2F00004.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&amp;refer=http%3A%2F%2Fpic.vjshi.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1629530659&amp;t=bbcfe1e86f393eecbb0722db1b92e475')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">北城韩雨</a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/"><i class="fa-fw fas fa-home faa-tada"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/shuoshuo/"><i class="fa-fw fas fa-archive faa-tada"></i><span> 叨逼叨</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/tags/"><i class="fa-fw fas fa-tags faa-tada"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/categories/"><i class="fa-fw fas fa-folder-open faa-tada"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/link/"><i class="fa-fw fas fa-link faa-tada"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/comments/"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-message"></use></svg><span> 留言板</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/about/"><i class="fa-fw fas fa-heart faa-tada"></i><span> 个人简介</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">面向对象</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2019-03-27T16:00:00.000Z" title="发表于 2019-03-28 00:00:00">2019-03-28</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2019-06-02T16:00:00.000Z" title="更新于 2019-06-03 00:00:00">2019-06-03</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/JS%E9%AB%98%E7%BA%A7/">JS高级</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">8.5k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>31分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="面向对象"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h2 id="编程思想"><a href="#编程思想" class="headerlink" title="编程思想"></a>编程思想</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> OOP 面向对象  js  java php python </span><br><span class="line"><span class="number">2.</span> POP 面向过程  c语言 </span><br></pre></td></tr></table></figure>
<h2 id="面向对象的概念"><a href="#面向对象的概念" class="headerlink" title="面向对象的概念"></a>面向对象的概念</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 我们js  所有的东西都可以理解为一个类</span><br><span class="line"><span class="number">2.</span> 比如我们的对象 数组 它上面所有的方法 都是从上面继承下来的</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">「数据类型类：我们见到的数据值都是所属类的一个实例」</span><br><span class="line">  + <span class="built_in">Number</span></span><br><span class="line">  + <span class="built_in">String</span></span><br><span class="line">  + <span class="built_in">Boolean</span></span><br><span class="line">  + <span class="built_in">Symbol</span></span><br><span class="line">  + BigInt</span><br><span class="line">  + <span class="built_in">Object</span></span><br><span class="line">    + <span class="built_in">Object</span></span><br><span class="line">    + <span class="built_in">Array</span></span><br><span class="line">    + <span class="built_in">RegExp</span></span><br><span class="line">    + <span class="built_in">Date</span></span><br><span class="line">    + ...</span><br><span class="line">  + <span class="built_in">Function</span></span><br><span class="line"></span><br><span class="line">「DOM对象/节点或元素集合/样式对象或者集合等」</span><br><span class="line">  + HTMLDivElement / HTMLAnchorElement / HTMLUListElement ... 每一种元素对象都有一个自己所属的类</span><br><span class="line">  + HTMLElement / XMLElement ...</span><br><span class="line">  + Element / Text / Document...</span><br><span class="line">  + Node 节点类</span><br><span class="line">  + EventTarget</span><br><span class="line">  + HTMLCollection / NodeList  ...</span><br><span class="line">  + CSSStyleDeclaration</span><br><span class="line">  + ......</span><br><span class="line"></span><br><span class="line">---------------</span><br><span class="line">学习JS基础知识，尤其是API层面的</span><br><span class="line">  + 类.prototype：存放的是给当前类的实例调用的公共属性方法</span><br><span class="line">  + 类.xxx：把其当作对象设定的静态私有属性方法</span><br><span class="line">  + ...</span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">&#x27;xxx&#x27;</span>)</span><br><span class="line">   + 获取上下文只能是<span class="built_in">document</span>?</span><br><span class="line">   + getElementById是在Document类原型上提供的方法，只有Document它的实例才可以调用(<span class="built_in">document</span>是它的实例)</span><br><span class="line"></span><br><span class="line">[context].getElementsByTagName(<span class="string">&#x27;*&#x27;</span>)</span><br><span class="line">   + Element类的原型上提供getElementsByTagName方法</span><br><span class="line">   + 每一个元素标签都是Element类的实例</span><br><span class="line">   + Document的原型上也有这个方法，所以<span class="built_in">document</span>也可以用</span><br><span class="line">   + ...</span><br></pre></td></tr></table></figure>
<h2 id="自定义类"><a href="#自定义类" class="headerlink" title="自定义类"></a>自定义类</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 上面的那些和方法 都是自己去写的类 也就是js 已经你写好的</span><br><span class="line"><span class="number">2.</span> 但是除了以上那些 还远远不够 所以 我们自己就又了自定义类 <span class="keyword">new</span> <span class="class"><span class="keyword">class</span></span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//普通函数执行</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sum</span> (<span class="params">x,y</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">let</span> total = x + y</span><br><span class="line">    <span class="built_in">this</span>.total = total</span><br><span class="line">    <span class="keyword">return</span> total</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> res = sum(<span class="number">10</span>,<span class="number">20</span>)</span><br><span class="line"><span class="built_in">console</span>.log(res) <span class="comment">//输出30</span></span><br></pre></td></tr></table></figure>
<p><img src="new.png" alt=""></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 当我们加了new 之后 执行的方式就不一样了</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sum</span> (<span class="params">x,y</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">let</span> total = x + y</span><br><span class="line">    <span class="built_in">this</span>.total = total</span><br><span class="line">    <span class="keyword">return</span> total</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> res = <span class="keyword">new</span> sum(<span class="number">10</span>,<span class="number">20</span>)</span><br><span class="line"><span class="built_in">console</span>.log(res) <span class="comment">//  &#123;total:30&#125; 执行结果</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="带-new-的函数执行都干了什么"><a href="#带-new-的函数执行都干了什么" class="headerlink" title="带 new 的函数执行都干了什么"></a>带 new 的函数执行都干了什么</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> <span class="keyword">new</span> 的函数执行  首先会和普通函数一样 形成上下文EC(XXX) AO(xxx) 初始化作用域链 形参赋值 变量提升 等等</span><br><span class="line"><span class="number">2.</span> <span class="keyword">new</span>的函数执行 在代码执行之前 私有上下文之前 会创建一个空对象</span><br><span class="line"><span class="number">3.</span> 然后初始化<span class="built_in">this</span>的时候  就会让我们的<span class="built_in">this</span> 指向我们创建的对象</span><br><span class="line"><span class="number">4.</span> 后期在代码执行过程中 如果遇到<span class="built_in">this</span>.xxx 都是给我们上面创建的那个实例对象创建私有的属性和方法</span><br><span class="line"><span class="number">5.</span> 如果没有些 <span class="keyword">return</span> 默认是把我们的创建的对象返回 如果自己写了 <span class="keyword">return</span>  自己返回的是基本类型值 写也没用 还是返回我们上面创建的那个对象 如果返回的是引用类型值 返回的是你自己写的引用类型</span><br><span class="line"><span class="number">6.</span> <span class="keyword">new</span> Fn 也相当于把函数执行了 不带列表的 <span class="keyword">new</span> 最后 Fn 都一定会执行 而且都会创造这个类的实例 区别 是否传递实参  以及运算优先级不一样</span><br><span class="line"><span class="number">7.</span> 所有的类都是一个函数数据类型值 内置类/自定义类</span><br><span class="line"><span class="number">8.</span> 每一次<span class="keyword">new</span> 类创造的实例都是 独立的实例对象 这种模式在js中叫做 构造函数模式</span><br></pre></td></tr></table></figure>
<p><img src="new-1.png" alt=""></p>
<h2 id="面向对象-原型prototype-和-原型链proto"><a href="#面向对象-原型prototype-和-原型链proto" class="headerlink" title="面向对象 原型prototype 和 原型链proto"></a>面向对象 原型prototype 和 原型链<strong>proto</strong></h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 每一个类(函数) 都具备 prototype(隐式原型) 并且属性值是一个对象</span><br><span class="line"><span class="number">2.</span> prototype 对象上天生具备一个属性 <span class="title">constructor</span> 指向类本身</span><br><span class="line">3. 每一个对象(<span class="params">普通对象、prototype、实例、函数等</span>)都具备<span class="title">__proto__</span>(<span class="params">显式原型</span>) 属性值是当前实例所属的原型</span><br><span class="line">4. 所有的类都是函数数据类型(<span class="params">包括内置类</span>) 所有的函数都天生自带一个属性 <span class="title">prototype</span> 属性值默认是一个对象数据类型 其存储的是 供实例能调用的公共属性和方法 </span><br><span class="line">5. 所有的对象数据类型值也天生自带一个属性<span class="title">__proto__</span>原型链 它的属性值:当前类的原型<span class="title">prototype</span> 实例.<span class="title">__proto__</span> = 类.<span class="title">prototype</span></span><br><span class="line">6. 如果我们调取了实例中的一个方法 它先看自己的实例上有没有 如果没有就去原型上找  这个就是原型链查找机制</span><br></pre></td></tr></table></figure>
<p><img src="prototype.png" alt=""></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//总结</span></span><br><span class="line"><span class="number">1.</span> 首先我们每个函数上面都有一个 prototype(原型)属性 是一个对象 对象里面有我们的<span class="title">constructor</span> 指向我们的函数本身</span><br><span class="line">2. 当<span class="title">new</span> 执行函数的时候 初始化的<span class="title">this</span>的时候 我们会单独开辟一块空间 创建一个实例对象 只要是对象就会有一个属性<span class="title">__proto__</span></span><br><span class="line">3. 每个对象上面 都有 一个<span class="title">__proto__</span> (<span class="params">原型链</span>)也是一个对象 如果这个函数是<span class="title">new</span> 执行的 那么 <span class="title">__proto__</span>指向的就是我们函数的 <span class="title">prototype</span></span><br><span class="line">4. 也就是说 实例对象(<span class="params"><span class="keyword">new</span> 执行函数的时候初始化<span class="built_in">this</span>出来的那个对象</span>).<span class="title">__proto__</span> =  类(<span class="params">也就是我们的构造函数</span>).<span class="title">prototype</span></span><br><span class="line">5. 我们函数的 <span class="title">prototype</span>(<span class="params">原型</span>) 也是一个对象 那么它也有一个<span class="title">__proto__</span> 指向应该是构造我们的<span class="title">prototype</span>的函数 那么这个函数就是 <span class="title">new</span> <span class="title">Object</span>(<span class="params"></span>)</span><br><span class="line">6. 所以 当我们一个类上的方法没有的时候 它就会去我们的原型上找 如果没有 就顺着原型链 一步一步的向上查找 最终找到我们的 <span class="title">Object</span> 函数 这就是 原型链查找机制</span><br></pre></td></tr></table></figure>
<h2 id="原型重定向"><a href="#原型重定向" class="headerlink" title="原型重定向"></a>原型重定向</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 原型重定向 就是把 prototype 的指针指向一个新的对象</span><br><span class="line"><span class="number">2.</span> 原型为啥要重定向 为了方便给原型上扩充属性和方法</span><br><span class="line"><span class="number">3.</span> 原型重定向 带来的问题是 新定向的原型对象上 没有<span class="title">constructor</span>属性 结构不完整 我们浏览器默认生成的原型对象因为缺少引用 会被释放掉 可能导致原始加入的属性和方法丢失掉</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Fn</span> (<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.x = <span class="number">100</span></span><br><span class="line">    <span class="built_in">this</span>.y = <span class="number">200</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 原始的原型对象</span></span><br><span class="line">Fn.prototype.getX = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;</span><br><span class="line"><span class="comment">//这个时候 就相当于给我们的原型重定向了 那么我们之前在prototype上的getX 这个方法也没有了 constructor也没有了 这种重定向 可以批量添加属性和方法</span></span><br><span class="line">Fn.prototype = &#123;</span><br><span class="line">    <span class="comment">//如果原始的原型对象不存在其他的属性和方法 我们只需要手动添加constructor 指向我们的类</span></span><br><span class="line">    <span class="title">constructor</span>:<span class="title">Fn</span></span><br><span class="line">    <span class="title">getY</span>:<span class="title">function</span>(<span class="params"></span>)&#123;&#125;,</span><br><span class="line">    getX:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;,</span><br><span class="line">    getZ:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;,</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//如果我们的原型对象上有别的属性 我们就需要合并进来</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> *    Fn.prototype = Object.assgin(Fn.prototype,&#123;</span></span><br><span class="line"><span class="comment"> *			getY:function()&#123;&#125;,</span></span><br><span class="line"><span class="comment"> *   		getX:function()&#123;&#125;,</span></span><br><span class="line"><span class="comment"> *  		getZ:function()&#123;&#125;,</span></span><br><span class="line"><span class="comment"> *	  &#125;)</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">let</span> f1 = <span class="keyword">new</span> Fn</span><br></pre></td></tr></table></figure>
<p><img src="prototype1.png" alt=""></p>
<h2 id="原型重写-new"><a href="#原型重写-new" class="headerlink" title="原型重写 new"></a>原型重写 new</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 我们自己来实现一个_new函数 </span><br><span class="line"><span class="number">2.</span> 这里就需要知道<span class="keyword">new</span>的时候 都干了什么 </span><br><span class="line"><span class="number">3.</span> 首先 <span class="keyword">new</span> 函数执行 和普通函数的执行一样  形成私有上下文 初始作用域链 形参赋值 变量提升 代码执行</span><br><span class="line"><span class="number">4.</span>  创建了一个空对象 <span class="built_in">this</span> 指向了它 对象.__proto__ = Dog.prototype </span><br><span class="line"><span class="number">5.</span> 把<span class="built_in">this</span> 指向 指向这个我们创建的空对象 如果没有 <span class="keyword">return</span> 或者返回的是基本类型值  则返回都是实例对象 否则返回我们自己定义的对象</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Dog</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name</span><br><span class="line">&#125;</span><br><span class="line">Dog.prototype.bark = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;<span class="built_in">console</span>.log(<span class="string">&#x27;wangwang&#x27;</span>)&#125;</span><br><span class="line">Dog.prototype.sanName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;<span class="built_in">console</span>.log(<span class="string">&#x27;my name is&#x27;</span> + <span class="built_in">this</span>.name)&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">_new</span> (<span class="params">func,...params</span>)</span>&#123;</span><br><span class="line">    <span class="comment">//1. 首先我们要创建一个实例对象</span></span><br><span class="line">    <span class="keyword">let</span> obj = &#123;&#125;</span><br><span class="line">    obj.__proto__ = func.prototype</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//2. 把类当作普通函数执行 并且让this 指向我们的实例对象</span></span><br><span class="line">    <span class="keyword">let</span> res = func.call(obj,...params)</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//3. 根据返回结果 决定返回啥</span></span><br><span class="line">    <span class="keyword">if</span>(res !== <span class="literal">null</span> &amp;&amp; (<span class="keyword">typeof</span> res === <span class="string">&#x27;object&#x27;</span> || <span class="keyword">typeof</span> res === <span class="string">&#x27;function&#x27;</span>)) <span class="keyword">return</span> res</span><br><span class="line">    <span class="keyword">return</span> obj</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> sanmao = _new(Dog,<span class="string">&#x27;dahuang&#x27;</span>,<span class="number">23</span>)</span><br><span class="line">sanmao.bark()</span><br><span class="line">samao.sayName()</span><br><span class="line"><span class="comment">// IE 我们使用不了__proto__ 所以就要用到下面的方法</span></span><br><span class="line"><span class="comment">// 创建了一个空对象 并且把对象A作为它的原型 空对象.__proto__ = 对象A</span></span><br><span class="line"><span class="built_in">Object</span>.create(obj)</span><br></pre></td></tr></table></figure>
<h2 id="基于内置类原型扩充方法"><a href="#基于内置类原型扩充方法" class="headerlink" title="基于内置类原型扩充方法"></a>基于内置类原型扩充方法</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 我们知道内置类 比如 <span class="built_in">Array</span> <span class="built_in">Object</span> 都是函数数据类型 就会有一个自己所属的堆内存 但是里面的代码我们看不到 就会有一个 native code </span><br><span class="line"><span class="number">2.</span> 每一个函数 都会自带一个属性 叫 prototype 属性值是一个对象 自带一个属性<span class="title">constructor</span> 指向自己构造函数本身 </span><br><span class="line">3. 像内置类的原型上扩充方法 最好设置私有前缀 而且扩充方法里面的<span class="title">this</span> 就是我们的当前实例</span><br><span class="line">4. 必须要保证 <span class="title">this</span> 是我们当前要操作的实例  </span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 我们用 数组去重举例 </span></span><br><span class="line"><span class="comment">//我们arr 都是我们 Array的实例  所以我们可以调用Array.prototype上的方法 </span></span><br><span class="line"><span class="keyword">let</span> arr = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="number">8</span>] </span><br><span class="line"><span class="built_in">Array</span>.prototype.myUnique = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="comment">//这里面的this 就是我们实例本身  所以首先我们要保证 this 是个数组</span></span><br><span class="line">    <span class="keyword">if</span>(!<span class="built_in">Array</span>.isArray(<span class="built_in">this</span>)) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">&#x27;不是一个数组&#x27;</span>)</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">Array</span>.from(<span class="keyword">new</span> <span class="built_in">Set</span>(<span class="built_in">this</span>))</span><br><span class="line">&#125;</span><br><span class="line">arr.myUnique() <span class="comment">//直接就可以去重</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 我们现在 实现一个加减 的方法</span></span><br><span class="line"><span class="keyword">let</span> n = <span class="number">10</span></span><br><span class="line"><span class="keyword">let</span> m = n.plus(<span class="number">10</span>).minus(<span class="number">5</span>)</span><br><span class="line"><span class="built_in">console</span>.log(m) <span class="comment">// (10+10-5) 15</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//如果我们基于原型上扩充方法</span></span><br><span class="line"><span class="built_in">Number</span>.prototype.plus = <span class="function"><span class="keyword">function</span>(<span class="params">num</span>) </span>&#123;</span><br><span class="line">    <span class="comment">//这里面我们输出this 发现并不是10 而是引用类型 Number(10) typeof this =&gt; &#x27;object&#x27;</span></span><br><span class="line">    <span class="comment">//这里所有的this 都不是基础类型的值 都是引用类型的值</span></span><br><span class="line">    <span class="comment">// 如果我们想变成基础类型值 我们需要用call apply bind 改变this 指向 变成基础类型值</span></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>) <span class="comment">// Number(10)</span></span><br><span class="line">    <span class="comment">// 我们知道 上面的就是个对象 对象 相加 就会变成 &#x27;[obejct object]10&#x27;</span></span><br><span class="line">    <span class="comment">// 但是我们这个方法是有原始值 会先调用valueOf获取原始值(number/string/boolean/Date)</span></span><br><span class="line">    <span class="comment">// 如果有原始值 就获取到结果即可并且参与到运算 如果没有就转换称字符串</span></span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">this</span> + num</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">Number</span>.prototype.minus = <span class="function"><span class="keyword">function</span>(<span class="params">num</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">this</span> - num</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//基于以上的总结</span></span><br><span class="line"><span class="number">1.</span> JS创建一个值有两种方法 一种是字面量 一种是构造函数</span><br><span class="line"><span class="keyword">let</span> n = <span class="number">10</span> <span class="comment">//字面量</span></span><br><span class="line"><span class="keyword">let</span> n = <span class="keyword">new</span> <span class="built_in">Number</span>(<span class="number">10</span>) <span class="comment">// number(10)</span></span><br><span class="line"><span class="number">2.</span>  上面不论哪种方法 创建出来的都是一个实例</span><br><span class="line"><span class="number">3.</span>  基础数据类型 上面的那辆创建方式 输出结果是不一样的 字面量 就是 <span class="number">10</span>  构造函数创造出来的就是引用类型 <span class="built_in">Number</span>(<span class="number">10</span>)</span><br><span class="line"><span class="number">4.</span> 我们字面量方式创造的值 在调用方法的时候 会默认 把字面量的方式 变成引用类型值 在去原型上调方法</span><br></pre></td></tr></table></figure>
<h2 id="函数的三种角色"><a href="#函数的三种角色" class="headerlink" title="函数的三种角色"></a>函数的三种角色</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 我们要知道 所有的函数 都是也都是 <span class="built_in">Function</span> 的内置类 置换出来的</span><br><span class="line"><span class="number">2.</span> 但是函数的内置类的原型 prototype 不是一个对象 是一个匿名空函数 但是操作上和其他类的原型一摸一样 没有啥却别 </span><br><span class="line"><span class="number">3.</span> 函数的三种角色普通函数执行 闭包作用域</span><br><span class="line">   构造函数执行 <span class="keyword">new</span> 类和实例</span><br><span class="line">   普通对象 键值对</span><br><span class="line"><span class="number">4.</span> 这三种角色之间没有必然的联系</span><br><span class="line"><span class="number">5.</span> 这里我们知道 我们的内置类<span class="built_in">Array</span> <span class="built_in">Object</span> <span class="built_in">Number</span> 这些也都是函数 那么函数也是一个对象 所以他们作为普函数来说 都会有__proto__ 都会指向我们 <span class="built_in">Function</span> 的prototype </span><br></pre></td></tr></table></figure>
<p><img src="function.png" alt=""></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//实例</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    getName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="number">1</span>);</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line">&#125;</span><br><span class="line">Foo.getName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="number">2</span>);</span><br><span class="line">&#125;;</span><br><span class="line">Foo.prototype.getName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="number">3</span>);</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">var</span> getName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="number">4</span>);</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getName</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="number">5</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 首先 函数记得有三种角色 第一种是 当作普通函数执行 第二种是 new 执行 第三种是 作为对象</span></span><br><span class="line"><span class="comment">// 这里就相当于 我们把Foo当作一个对象 访问了它的getName属性执行 所所以输出结果是 2</span></span><br><span class="line">Foo.getName(); <span class="comment">// 2</span></span><br><span class="line"><span class="comment">// 这里就是执行全局的函数getName() 全局我们可以看到 第一次函数是5 但是 后来 有重新把函数赋值了 所以输出 是4</span></span><br><span class="line">getName(); <span class="comment">// 4</span></span><br><span class="line"><span class="comment">// 这里是当作普通函数执行 普通函数执行return this  这里的this 是window 但是 函数执行的时候 又把全局的getName()重新写了 所以就相当于调window.getName() 是1</span></span><br><span class="line">Foo().getName(); <span class="comment">// 1</span></span><br><span class="line"><span class="comment">//因为全局的函数已经被重新了 所以输出是1</span></span><br><span class="line">getName(); <span class="comment">// 1</span></span><br><span class="line"><span class="comment">// 这就存在优先级的问题 是new 函数执行的优先级搞 还是 成员访问的优先级高</span></span><br><span class="line"><span class="comment">// obj.xxx 访问的优先级 是 19 new Fn() 带参数 是19  new Fn 是18 如果优先级相同那么就从左向右一次执行</span></span><br><span class="line"><span class="comment">// 所以我们要先执行Foo.getName() 就相当于 执行了 new function()&#123;console.log(2)&#125; new的时候函数也会执行 所以 输出的是2</span></span><br><span class="line"><span class="keyword">new</span> Foo.getName(); <span class="comment">//2</span></span><br><span class="line"><span class="comment">// 这里 由于两个优先级 都是相同的 所以 从左向右一次执行  所以这里new Foo()执行 创建了实例对象 this 指向了这个实例对象 那么这个实例对象上没有getName() 就要像原型上找 也就是Foo.prototype.getName() //所以输出结果是3</span></span><br><span class="line"><span class="keyword">new</span> Foo().getName(); <span class="comment">//3 </span></span><br><span class="line"><span class="comment">//这里从上面一样 只不过最后当普通函数执行了 输出结果也是3</span></span><br><span class="line"><span class="keyword">new</span> <span class="keyword">new</span> Foo().getName(); <span class="comment">//3</span></span><br></pre></td></tr></table></figure>
<p><img src="function2.png" alt=""></p>
<h2 id="THIS种的五种情况"><a href="#THIS种的五种情况" class="headerlink" title="THIS种的五种情况"></a>THIS种的五种情况</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span>  给当前元素的某个事件行为 绑定方法 当事件行为触发 方法执行 方法种的<span class="built_in">this</span> 一般都是 当前操作元素 排除IE6~<span class="number">8</span>中 基于 attachEvent进行的DOM2事件绑定 方法中的 <span class="built_in">this</span> 是 <span class="built_in">window</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">document</span>.body.onclick = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="built_in">console</span>.log(<span class="built_in">this</span>) &#125; <span class="comment">//输出是body</span></span><br><span class="line"><span class="built_in">document</span>.body.addEventListenner(<span class="string">&#x27;click&#x27;</span>,<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;<span class="built_in">console</span>.log(<span class="built_in">this</span>)&#125;) <span class="comment">//输出是body</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">2.</span> 函数执行(看函数前面是否右点) 点前面是谁 <span class="built_in">this</span> 就是谁 没有点 <span class="built_in">this</span> 是<span class="built_in">window</span> 严格模式下 是<span class="literal">undefined</span> 匿名函数(自调用函数/回调函数) 一般<span class="built_in">this</span> 就是<span class="built_in">window</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> fun = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="built_in">console</span>.log(<span class="built_in">this</span>) &#125;</span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    name:<span class="string">&#x27;obj&#x27;</span>,</span><br><span class="line">    fn:fun</span><br><span class="line">&#125;</span><br><span class="line">fun() <span class="comment">//输出this 是 window  严格模式下 use strict undefined</span></span><br><span class="line">obj.fn() <span class="comment">// this 是obj</span></span><br><span class="line">(obj.fn)() <span class="comment">//同上</span></span><br><span class="line"><span class="comment">//括号表达式  括号里面有多项的情况下 只取最后一项 </span></span><br><span class="line">(<span class="number">10</span>,<span class="number">20</span>,obj.fn)() <span class="comment">// this 是window</span></span><br><span class="line"><span class="comment">//自调用函数</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;<span class="built_in">console</span>.log(<span class="built_in">this</span>)&#125;)() <span class="comment">// window</span></span><br><span class="line"><span class="comment">//数组的回调函数</span></span><br><span class="line">[<span class="number">1</span>,<span class="number">2</span>].sort(<span class="function">() =&gt;</span> &#123;<span class="built_in">console</span>.log(<span class="built_in">this</span>)&#125;) <span class="comment">// window</span></span><br><span class="line"><span class="comment">// forEach</span></span><br><span class="line">[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>].forEach(<span class="function">(<span class="params">item</span>)=&gt;</span><span class="built_in">console</span>.log(<span class="built_in">this</span>),obj) <span class="comment">//这里forEach处理了改变了this指向 就是obj </span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">3.</span> 构造函数 <span class="keyword">new</span> 执行 函数体中的<span class="built_in">this</span> 是当前的实例</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Fn</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.x = <span class="number">100</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//普通函数执行 this 是window</span></span><br><span class="line">Fn()</span><br><span class="line"><span class="comment">// new 执行 this 是实例本身 也就是f</span></span><br><span class="line"><span class="keyword">const</span> f  = <span class="keyword">new</span> Fn()</span><br><span class="line">Fn.prototype.say = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="built_in">console</span>.log(<span class="built_in">this</span>.x) &#125;</span><br><span class="line"><span class="comment">// 本身私有属性上没有这个方法 就去原型prototype去找 由于是f的实例调取的 所以this 是f </span></span><br><span class="line">f.say()</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">4.</span> 箭头函数中 或者 基于&#123;&#125; 形成的块级上下文 里面没有 <span class="built_in">this</span>  如果 代码中有<span class="built_in">this</span> 也不是函数自己的 而是 自己所在的上下文中的</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    name:<span class="string">&#x27;obj&#x27;</span>,</span><br><span class="line">    <span class="function"><span class="title">fn</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="built_in">this</span>.name = <span class="string">&#x27;xxx&#x27;</span></span><br><span class="line">        &#125;,<span class="number">1000</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">obj.fn()  <span class="comment">//这里面的定时器 this 是window </span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果是箭头函数 他就会去找上一层的this 也就是我们函数定义的上下文 上一层的this 取决于谁调用</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    name:<span class="string">&#x27;obj&#x27;</span>,</span><br><span class="line">    <span class="function"><span class="title">fn</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="comment">//或者我们也可以 把this 先存期来 let _that = this</span></span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">//_that.name = xxx</span></span><br><span class="line">        	<span class="built_in">this</span>.name = <span class="string">&#x27;xxx&#x27;</span></span><br><span class="line">        &#125;,<span class="number">1000</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">5.</span> 我们可以基于<span class="keyword">function</span>.prototype 上的call / apply /bind 去改变<span class="built_in">this</span> 指向 但是对于箭头函数无用</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> fn = <span class="function"><span class="keyword">function</span> <span class="title">fn</span> (<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">window</span>.name = <span class="string">&#x27;xxx&#x27;</span></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    name:<span class="string">&#x27;obj&#x27;</span>,</span><br><span class="line">    fn:fn</span><br><span class="line">&#125;</span><br><span class="line">fn()  <span class="comment">// 输出 是 window.name</span></span><br><span class="line">obj.fn() <span class="comment">// 输出是 obj.name</span></span><br><span class="line"><span class="comment">// 如果 obj 里面没有fn 属性  但是我们还想让fn的this 指向 obj 那么就要用到call appply bind</span></span><br><span class="line">fn.call(obj,这里面还可以传参)</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// call 的执行逻辑</span></span><br><span class="line">fn.call(obj,<span class="number">10</span>,<span class="number">20</span>)</span><br><span class="line">首先 fn 基于原型链__proto__ 找到 <span class="built_in">Function</span>.prototype.call 方法 并且把call 方法执行</span><br><span class="line">call 方法中的<span class="built_in">this</span> 就是 当前操作的实例fn 传递给call 方法的第一个实参 是未来改变fn中的<span class="built_in">this</span> 指向 剩余参数 都是未来要一次传递给fn的参数信息</span><br><span class="line">call 方法执行的过程中 这样处理 把fn[call中的<span class="built_in">this</span>]执行 让fn 中的<span class="built_in">this</span> 指向obj 并且把参数也传递进去</span><br><span class="line">call 如果第一个参数 如果不传 或者传 <span class="literal">null</span> / <span class="literal">undefined</span>  在js 非严格模式下 最后fn 中的<span class="built_in">this</span> 都是<span class="built_in">window</span> (严格模式下 不传<span class="built_in">this</span> 是<span class="literal">undefined</span>) fn.call(<span class="number">10</span>,<span class="number">20</span>) <span class="comment">//fn this -&gt; 10</span></span><br><span class="line"><span class="comment">// apply </span></span><br><span class="line">和call 一样 只不过传参的时候 后面的 要以数组的形式 fn.apply(obj,[<span class="number">10</span>,<span class="number">20</span>])</span><br><span class="line"><span class="comment">// bind 是预先处理 执行bind 先把函数中需要改变的this 等存储起来 但是此时函数不会被执行 执行bind的时候 会返回一个匿名函数 当后期执行匿名函数的死后 再去把之前需要执行的函数执行 并且改变this 为预设的值</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 定时器中的call</span></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    name:<span class="string">&#x27;obj.name&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">window</span>.name = <span class="string">&#x27;window.name&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 这样是不行的  我们call 方法 在改变this 的时候 是立即执行的 这样是不可以的1000之后就不在执行了</span></span><br><span class="line"><span class="built_in">setTimeout</span>(fn.call(obj),<span class="number">1000</span>)</span><br><span class="line"><span class="comment">//解决方法   我们把它写在一个函数里</span></span><br><span class="line">setTiomeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    fn.call(obj)</span><br><span class="line">&#125;,<span class="number">1000</span>)</span><br><span class="line"><span class="comment">//解决方法 用bind 因为bind 是返回一个柯里化函数</span></span><br><span class="line"><span class="built_in">setTimeout</span>(fn.bind(obj),<span class="number">1000</span>)</span><br></pre></td></tr></table></figure>
<h2 id="手写call-apply-bind-源码"><a href="#手写call-apply-bind-源码" class="headerlink" title="手写call / apply / bind 源码"></a>手写call / apply / bind 源码</h2><h3 id="手写-bind"><a href="#手写-bind" class="headerlink" title="手写 bind"></a>手写 bind</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span> (<span class="params">x,y</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.total = x + y</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    name:<span class="string">&#x27;obj的名字&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//我们普通的点击事件 就要执行一个函数 里面还有事件对象的参数</span></span><br><span class="line"><span class="built_in">document</span>.body.onclick = <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>&#123;</span><br><span class="line">    <span class="comment">//这里面的this是我们的body</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 所以 我们用 bind 的时候 首先也要返回一个函数 并且要传递事件对象 并且要改变this 指向</span></span><br><span class="line">documnet.body.onclick = fn.myBind(obj,<span class="number">10</span>,<span class="number">20</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">Function</span>.prototype.myBind = <span class="function"><span class="keyword">function</span> (<span class="params">context,...params</span>) </span>&#123;</span><br><span class="line">    <span class="comment">//首先这里面的this 是我们的fn 函数 因为是 fn 调取的myBind 函数 </span></span><br><span class="line">    <span class="comment">//context -&gt; 你传进来的obj对象</span></span><br><span class="line">    <span class="comment">//params -&gt; 是 你传进来的是10 20</span></span><br><span class="line">    <span class="comment">// 这里面我们要retrun 一个匿名函数 anonymous 也就是点击body的时候要执行的匿名函数</span></span><br><span class="line">    <span class="keyword">let</span> _that = <span class="built_in">this</span></span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> <span class="title">anonymous</span> (<span class="params">...arg</span>) </span>&#123;</span><br><span class="line">        <span class="comment">//首先这里面的this 因为是body调取的这个函数 所以 this 是body</span></span><br><span class="line">        <span class="comment">//2. 所以就需要我们拿到外面缓存的that</span></span><br><span class="line">        _that.call(obj,...params.concat(arg))</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//当然 这里我们也可以写成箭头函数的形式 这样就不用缓存this 了 它会去它所所以的上下文中的上层去找this</span></span><br><span class="line"><span class="built_in">Function</span>.prototype.myBind = <span class="function"><span class="keyword">function</span> (<span class="params">context,...params</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="function">(<span class="params">...arg</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">//首先这里面的this 因为是body调取的这个函数 所以 this 是body</span></span><br><span class="line">        <span class="comment">//2. 所以就需要我们拿到外面缓存的that</span></span><br><span class="line">        _that.call(obj,...params.concat(arg))</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="手写call"><a href="#手写call" class="headerlink" title="手写call"></a>手写call</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// call 和 apply  是立即执行 不会像bind 一样 赶回一个匿名函数</span></span><br><span class="line"><span class="built_in">Function</span>.prototype.myCall = <span class="function"><span class="keyword">function</span> (<span class="params">context,...params</span>)</span>&#123;</span><br><span class="line">    <span class="comment">//context -&gt; 就是你传进来的obj</span></span><br><span class="line">    <span class="comment">// ...params 就是你传进来的参数</span></span><br><span class="line">    <span class="comment">// 这里面的this 就是你的fn 函数 因为是fn 调用的 myCall</span></span><br><span class="line">    <span class="comment">// 首先 我们要让我们fn 和我们的obj 产生关系 比如 obj.fn = fn 这样再掉用fn的时候 this 就是我们的obj了</span></span><br><span class="line">    <span class="comment">//其次 我们在obj 上添加了一个fn 的属性 需要注意两点 第一个 fn是你自己后添加的所以用完需要删除 第二 如果人家obj上原本就有一个fn的属性 你就把人家的覆盖了 所以我们要用Symbol来确定唯一</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">//如果你传进来的是个undefined 或者null 我们都要把this 指向window 这里 在两个等于 == undfined 和 null 是相等 如果是三个等于就不等了</span></span><br><span class="line">    context == <span class="literal">null</span> ? context = <span class="built_in">window</span> : <span class="literal">null</span></span><br><span class="line">    <span class="comment">// 如果你的context 不是一个引用类型的值 而是基础类型的值 比如数字10 我们就需要先把它处理成 引用类型值 比如传进来的是个10 我们就处理称 Number(10) 这样就可以添加this</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 如果你的类型不是object 和 function 就说明 你是基础类型值 那么我们就需要处理 如果是我们就什么也不干</span></span><br><span class="line">    !<span class="regexp">/^(object|function)$/i</span>.test(<span class="keyword">typeof</span> context) ? context = object(context) : <span class="literal">null</span></span><br><span class="line">    <span class="keyword">let</span> result</span><br><span class="line">        <span class="comment">//这里我们需要创建一个唯一的属性值 来避免你原来obj上的属性值冲突</span></span><br><span class="line">    	key = <span class="built_in">Symbol</span>(<span class="string">&#x27;key&#x27;</span>)</span><br><span class="line">    <span class="comment">//让fn 函数 和我们的obj 家里关系</span></span><br><span class="line">    context[key] = <span class="built_in">this</span></span><br><span class="line">    result =  context[key](...params)</span><br><span class="line">    <span class="comment">// 用完之后 把我们新增的删除</span></span><br><span class="line">    <span class="keyword">delete</span> context[key]</span><br><span class="line">    <span class="comment">// 如果有返回值 就返回 </span></span><br><span class="line">    <span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="js中的继承"><a href="#js中的继承" class="headerlink" title="js中的继承"></a>js中的继承</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> JS 本身是基于面向对象开发的 编程语言 我们学习 就是学习的它的类</span><br><span class="line"><span class="number">2.</span> 那么类 就具备 封装 继承 多态</span><br><span class="line"><span class="number">3.</span> 封装 类也是一个函数 把实现一个功能的代码进行封装 实现 低耦合高内聚</span><br><span class="line"><span class="number">4.</span> 多态 又分为 重写 和 重载</span><br><span class="line">   重写  子类 可以重写 父类上的方法(伴随这继承)</span><br><span class="line">   重载  相同的方法 由于参数或者返回值不同 具备了不同的功能(js 不具备严格意义上的重载)</span><br><span class="line"><span class="number">5.</span> 子类可以继承父类中的方法</span><br></pre></td></tr></table></figure>
<h3 id="原型继承"><a href="#原型继承" class="headerlink" title="原型继承"></a>原型继承</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 原型继承 其实就是让 子类的原型 prototype 指向 父类的实例 </span><br><span class="line"><span class="number">2.</span> 把实例上的方法 和属性 都变成子类共有的</span><br><span class="line"><span class="number">3.</span> 父类中私有和共有的属性方法最后都变成子类实例共有的 但是和其他语言不同的是 原型继承并不会把父类的属性方法 拷贝 给子类 而是让子类实例基于__proto__ 原型链找到自己定义的属性和方法</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params"></span>) </span>&#123; <span class="built_in">this</span>.x = <span class="number">100</span> &#125;</span><br><span class="line">Parent.prototype.getX = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="keyword">return</span> <span class="built_in">this</span>.x &#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span> (<span class="params"></span>) </span>&#123; <span class="built_in">this</span>.y = <span class="number">200</span> &#125;</span><br><span class="line"><span class="comment">//现在CHild 想用 Parent的方法 所以我们就让 Child 的 原型 prototype = new Parent </span></span><br><span class="line">Child.prototype = <span class="keyword">new</span> Parent</span><br><span class="line">Child.prototype.getY = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="keyword">return</span> <span class="built_in">this</span>.y &#125;</span><br><span class="line"><span class="keyword">let</span> c1 = <span class="keyword">new</span> Child</span><br></pre></td></tr></table></figure>
<p><img src="jicheng.bmp" alt=""></p>
<h3 id="call继承"><a href="#call继承" class="headerlink" title="call继承"></a>call继承</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 我们刚刚看到原型继承  父类 私有的 和父类公有的 属性和方法 都变成子类实列公有的了 这样不是我们期待的</span><br><span class="line"><span class="number">2.</span> 所以有了call 继承 但是 只是把父类私有的 变成子类公有的 但是并没有 把父类公有的 变成子类公有的</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span> (<span class="params"></span>) </span>&#123; <span class="built_in">this</span>.x = <span class="number">100</span> &#125;</span><br><span class="line">Parent.prototype.getX = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="keyword">return</span> <span class="built_in">this</span>.x &#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span> (<span class="params"></span>) </span>&#123; </span><br><span class="line">    <span class="comment">//这里面的this 就是 Child 我们需要把Parent 里面的this 指向成我们 Child 所以就用了call</span></span><br><span class="line">    Parent.call(<span class="built_in">this</span>)</span><br><span class="line">    <span class="built_in">this</span>.y = <span class="number">200</span> </span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//以上 我们就把Paret里面的 x 变成 我们 Child 里面 的 y 了 这样就把 我们的 Parent里的y 变成我们Child 里私有的了 但是Parent 里面的 公有的方法 却没有继承过来</span></span><br></pre></td></tr></table></figure>
<h3 id="寄生组合式继承"><a href="#寄生组合式继承" class="headerlink" title="寄生组合式继承"></a>寄生组合式继承</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 就是 把我们的原型继承 和我们的call 继承 组合其来</span><br><span class="line"><span class="number">2.</span> 这样的好处 就是 把父类私有的 变成 子类 私有的 父类公共的 变成 子类中公有的</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params"></span>) </span>&#123; <span class="built_in">this</span>.x = <span class="number">100</span> &#125;</span><br><span class="line">Parent.prototype.getX = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="keyword">return</span> <span class="built_in">this</span>.x &#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span> (<span class="params"></span>) </span>&#123; <span class="built_in">this</span>.y = <span class="number">200</span> &#125;</span><br><span class="line"><span class="comment">//这里就是 把我们的基于我们原型链上去 查找 我们的 这样我们的父类的私有属性 就 就带入不到 我们的子类里面去了</span></span><br><span class="line">Child.prototype.__proto__ = Parent.prototype </span><br><span class="line">Child.prototype.getY = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="keyword">return</span> <span class="built_in">this</span>.y &#125;</span><br><span class="line"><span class="keyword">let</span> c1 = <span class="keyword">new</span> Child</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 但是以上的方法 在IE中这个方法并不可用 所以我们需要是用Object.create()</span></span><br><span class="line"><span class="comment">// Object.create()  就是创建一个空对象 并且 把这个空对象的原型链 __proto__ 指向 我们的传进来的 这个对象</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params"></span>) </span>&#123; <span class="built_in">this</span>.x = <span class="number">100</span> &#125;</span><br><span class="line">Parent.prototype.getX = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="keyword">return</span> <span class="built_in">this</span>.x &#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span> (<span class="params"></span>) </span>&#123; <span class="built_in">this</span>.y = <span class="number">200</span> &#125;</span><br><span class="line"><span class="comment">//直接 让我们一个 prototype = &#123;&#125; 这个 对象里面__proto__ 指向了我们的 Parent.prototype</span></span><br><span class="line">Child.prototype = <span class="built_in">Object</span>.create(Parent.prototype) </span><br><span class="line">Child.prototype.constructor = Child</span><br><span class="line">Child.prototype.getY = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="keyword">return</span> <span class="built_in">this</span>.y &#125;</span><br><span class="line"><span class="keyword">let</span> c1 = <span class="keyword">new</span> Child</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//实例</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">C1</span>(<span class="params"></span>) </span>&#123; <span class="keyword">if</span> (name)&#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name</span><br><span class="line">&#125;&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">C2</span>(<span class="params"></span>) </span>&#123; <span class="built_in">this</span>.name = name&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">C3</span>(<span class="params"></span>) </span>&#123; <span class="built_in">this</span>.name = name || <span class="string">&#x27;join&#x27;</span>&#125;</span><br><span class="line">C1.prototype.name = <span class="string">&#x27;Tom&#x27;</span></span><br><span class="line">C2.prototype.name = <span class="string">&#x27;Tom&#x27;</span></span><br><span class="line">C3.prototype.name = <span class="string">&#x27;Tom&#x27;</span></span><br><span class="line"><span class="keyword">new</span> C1().name <span class="comment">//有条件判断 没有走if 所以name 属性就要去自己原型上找 是Tom</span></span><br><span class="line"><span class="keyword">new</span> C2().name <span class="comment">//name 作为形参 没有传 所以值是undefined </span></span><br><span class="line"><span class="keyword">new</span> C3().name <span class="comment">// name 没传 但是走了或者的逻辑 所以 值是 join</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//示例 </span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Fn</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> a = <span class="number">1</span></span><br><span class="line">    <span class="built_in">this</span>.a = a</span><br><span class="line">&#125;</span><br><span class="line">Fn.prototype.say = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.a = <span class="number">2</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//这里我们Fn函数的原型prototype 就指向一个对象 里面有 constructor:Fn 这里 我们重新new Fn就相当于把 Fn.prototype指向了 new出来的fn的实例对象 但是Fn的原来的原型并没有销毁还在内存中  实例对象有一个__proto__ 它指向了Fn的原型</span></span><br><span class="line">Fn.prototype = <span class="keyword">new</span> Fn</span><br><span class="line"><span class="comment">// new Fn 的实例</span></span><br><span class="line"><span class="keyword">let</span> f1 = <span class="keyword">new</span> Fn</span><br><span class="line">Fn.prototype.b = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="built_in">this</span>.a = <span class="number">3</span>&#125;</span><br><span class="line"><span class="built_in">console</span>.log(f1.a) <span class="comment">// f1上的a 是1 因为 new 的时候也当普通函数执行了</span></span><br><span class="line"><span class="built_in">console</span>.log(f1.prototype) <span class="comment">//undefined f1的实例上没有prototype这个属性 只有在类的函数上才有</span></span><br><span class="line"><span class="built_in">console</span>.log(f1.b) <span class="comment">//是个函数</span></span><br><span class="line"><span class="built_in">console</span>.log(f1.hasOwnProperty(<span class="string">&#x27;b&#x27;</span>))<span class="comment">// false  这个是判断b 是不是 f1的私有属性 b函数并没在私有上 而是在 公有上 所以是false</span></span><br><span class="line"><span class="built_in">console</span>.log( <span class="string">&#x27;b&#x27;</span> <span class="keyword">in</span> f1) <span class="comment">// true  这个不一样 只要私有 原型上都能找到啊 </span></span><br><span class="line"><span class="built_in">console</span>.log(f1.constructor == fn) <span class="comment">// true  会从原型链上一点一点向上找</span></span><br></pre></td></tr></table></figure>
<p><img src="yuanxing.bmp" alt=""></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//实例</span></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    <span class="number">2</span>:<span class="number">3</span></span><br><span class="line">    <span class="number">3</span>:<span class="number">4</span></span><br><span class="line">    length:<span class="number">2</span></span><br><span class="line">    push:<span class="built_in">Array</span>.prototype.push</span><br><span class="line">&#125;</span><br><span class="line">obj.push(<span class="number">1</span>)</span><br><span class="line">obj.push(<span class="number">2</span>)</span><br><span class="line"><span class="built_in">console</span>.log(obj)</span><br><span class="line"><span class="comment">//以上我们要了解一下数组中的push 是怎么实现的</span></span><br><span class="line"><span class="keyword">let</span> arr = [<span class="number">10</span>,<span class="number">20</span>]</span><br><span class="line">arr.push(<span class="number">30</span>)</span><br><span class="line"><span class="built_in">Array</span>.prototype.push = <span class="function"><span class="keyword">function</span> (<span class="params">val</span>) </span>&#123;</span><br><span class="line">    <span class="comment">//这里面的this 是arr </span></span><br><span class="line">    <span class="comment">//这里面的代码 执行如下 相当于把代码的最后一位等于你添加进来的值</span></span><br><span class="line">    <span class="built_in">this</span>[<span class="built_in">this</span>.length] = val</span><br><span class="line">    <span class="comment">// arr[arr.length] = val</span></span><br><span class="line">    <span class="built_in">this</span>.length++</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//我们知道以上的方法执行再来看我们的obj</span></span><br><span class="line">obj.push(<span class="number">1</span>)</span><br><span class="line"><span class="comment">//这里执行的就是我们上面数组里面写的方法</span></span><br><span class="line">obj.push = <span class="function"><span class="keyword">function</span> (<span class="params">val</span>) </span>&#123;</span><br><span class="line">    <span class="comment">//这里的this 就是obj</span></span><br><span class="line">    <span class="built_in">this</span>[<span class="built_in">this</span>.length] = val</span><br><span class="line">    <span class="comment">//obj[obj.length = 2] = 1</span></span><br><span class="line">    obj[<span class="number">2</span>] = <span class="number">1</span></span><br><span class="line">    obj.length++</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//以上下的步骤都是如此 所以最后输出obj</span></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    <span class="number">2</span>:<span class="number">1</span></span><br><span class="line">    <span class="number">3</span>:<span class="number">2</span></span><br><span class="line">    length:<span class="number">4</span> <span class="comment">// 由于每次执行push方法之后 length都会++ 先从2 加加 成3 有从 3 加加到 4</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 实例</span></span><br><span class="line"> 我们知道 如果 == 两边类型不一样的话 都是转换成字符串 在转换成数字</span><br><span class="line"> 那么 比如对象 &#123;&#125; [] 转换成 数字的话 都是调取的原始值</span><br><span class="line"> 浏览器底层机制 会预先处理 使用 [<span class="built_in">Symbol</span>.toPrimitive] 这方法去获取原始值在转换成数字</span><br><span class="line"> 可是这个方法如果不存在 就会去调用valueOf方法(基本数据类型值上 比如 number string date)都会有这个方法 如果没有 就会调 toString 去转换为字符串 在把字符串 变换成数字</span><br><span class="line"> <span class="comment">// 所以如下提</span></span><br><span class="line"> <span class="keyword">let</span> a = ?  <span class="comment">// a等于多少的时候  能输出ok</span></span><br><span class="line"> <span class="keyword">if</span>(a==<span class="number">1</span> &amp;&amp; a == <span class="number">2</span> &amp;&amp; a ==<span class="number">3</span> )&#123;</span><br><span class="line">     <span class="built_in">console</span>.log(<span class="string">&#x27;ok&#x27;</span>)</span><br><span class="line"> &#125;</span><br><span class="line"><span class="comment">//所以我们知道 根据以上规则 它肯定回去调[Symbol.toPrimitive] 这个方法 但是 没有所以我们要自己写一个</span></span><br><span class="line"><span class="keyword">let</span> a = &#123;</span><br><span class="line">    value:<span class="number">0</span>,</span><br><span class="line">    [<span class="built_in">Symbol</span>.toPrimitive](hint)&#123;</span><br><span class="line">        <span class="comment">// 浏览器调取这个方法的时候 会传递一个hint 存储当前对象即将转换什么值</span></span><br><span class="line">        <span class="keyword">return</span> ++<span class="built_in">this</span>.value</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//这个时候 两个等号比较的时候 如果类型不一样会先转换成数字 基于以上的规律获取原始值 则会调用 Symbol.toPrimitive 这个方法 这个方法是我们写的(因为自己写了) a==1 的时候 会调取一次 value就++了 a==2 还会调取一次 </span></span><br><span class="line"><span class="keyword">if</span>( a== <span class="number">1</span> &amp;&amp; a == <span class="number">2</span> &amp;&amp; a ==<span class="number">3</span>)&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;ok&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//还有第二种写法</span></span><br><span class="line"><span class="keyword">let</span> a = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]</span><br><span class="line"><span class="comment">// 代码逻辑 a.shift 删除 1 然后在转换为字符串 返回的就是1 然后 继续删除2在转换为字符串 也可以走进上面的那个if里面去</span></span><br><span class="line">a.toString = a.shift</span><br><span class="line"><span class="comment">// 方案2 用数据劫持</span></span><br><span class="line"><span class="keyword">let</span> i = <span class="number">0</span></span><br><span class="line"><span class="comment">//看看a 是不是window的一个属性</span></span><br><span class="line"><span class="built_in">Object</span>.defineProperty(<span class="built_in">window</span>,<span class="string">&#x27;a&#x27;</span>,&#123;</span><br><span class="line">    <span class="function"><span class="title">get</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> ++i</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">if</span>(a == <span class="number">1</span> &amp;&amp; a == <span class="number">2</span> &amp;&amp; a == <span class="number">3</span>)&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;ok&#x27;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="数组对象的深克隆-浅克隆"><a href="#数组对象的深克隆-浅克隆" class="headerlink" title="数组对象的深克隆/浅克隆"></a>数组对象的深克隆/浅克隆</h2><h3 id="浅克隆"><a href="#浅克隆" class="headerlink" title="浅克隆"></a>浅克隆</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 浅克隆 就是 把一级对象 拷贝一份 如果对象里面还有引用类型的值 是拷贝不了的</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    a:<span class="number">100</span>,</span><br><span class="line">    b:[<span class="number">10</span>,<span class="number">20</span>],</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//浅克隆</span></span><br><span class="line"><span class="keyword">let</span> newObj = &#123;...obj&#125;</span><br><span class="line">newObj === obj <span class="comment">// 输出 false 因为地址不一样了</span></span><br><span class="line">newObj.b === obj.b <span class="comment">// 输出 true 因为地址没有拷贝过来</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//for in 循环拷贝 </span></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> key <span class="keyword">in</span> obj)&#123;</span><br><span class="line">    <span class="comment">//这里注意 for in 遍历 会把当前对象上可枚举(列举)的属性 就是你能看到的都会拷贝 原型上的也会</span></span><br><span class="line">    <span class="comment">// 但是除了一些内置属性是不可枚举的 比如 数组的length 虽然可以看到 但是 不会被拷贝</span></span><br><span class="line">    <span class="comment">//公有属性 大部分都是不可枚举的 但是自己在内置类原型上扩展的 是可枚举的 也就是可以拷贝</span></span><br><span class="line">    <span class="keyword">if</span>(!obj.hasOwnProoerty(key)) <span class="keyword">break</span></span><br><span class="line">    newObj[key] = obj[key]</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> <span class="keyword">of</span> 循环 只会拷贝 私有的</span><br></pre></td></tr></table></figure>
<h3 id="深克隆"><a href="#深克隆" class="headerlink" title="深克隆"></a>深克隆</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 方案一  都变成字符串 在重新变成对象 这样浏览器会重新开辟全套的内存空间存储信息 比如 <span class="built_in">JSON</span>.Stringify / <span class="built_in">JSON</span>.parse</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 缺点 值如果是 正则 Symbol(&#x27;AA&#x27;) BigInt 函数 日期对象(会变成字符串) 都会拷贝不过来</span></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    a:<span class="number">100</span>,</span><br><span class="line">    b:[<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>],</span><br><span class="line">    c:&#123;<span class="attr">x</span>:<span class="number">10</span>&#125;,</span><br><span class="line">    d:<span class="regexp">/^\d+s/</span>,  <span class="comment">//正则在用JSON 拷贝的时候 会变成&#123;&#125; 空对象</span></span><br><span class="line">    e:<span class="built_in">Symbol</span>(<span class="string">&#x27;AA&#x27;</span>) <span class="comment">// 不会被拷贝 直接没有e这个属性</span></span><br><span class="line">    f:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125; <span class="comment">// 函数同上</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">2.</span> 方案二 自己单独一层一层处理</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">cloneDeep</span> (<span class="params">obj</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span>	type = <span class="keyword">typeof</span> obj</span><br><span class="line">    <span class="keyword">if</span>(obj == <span class="literal">null</span>) <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">    <span class="comment">//如果传递的不是对象类型 就直接返回对应的值</span></span><br><span class="line">    <span class="keyword">if</span>(type !== <span class="string">&#x27;object&#x27;</span>) <span class="keyword">return</span> obj</span><br><span class="line">    <span class="comment">//知道 传进来的是什么类型</span></span><br><span class="line">    <span class="keyword">let</span> <span class="title">constructor</span> = <span class="title">obj</span>.<span class="title">constructor</span></span><br><span class="line">    //如果是正则 或者 日期 对象 <span class="title">constructor</span> 就是你的构造函数 可能是 <span class="title">new</span> <span class="title">RegExp</span> | <span class="title">Date</span></span><br><span class="line">    <span class="title">if</span>(<span class="params"><span class="regexp">/^(RegExp|Date)$/i</span>.test(constructor.name)</span>) <span class="title">return</span> <span class="title">new</span> <span class="title">constructor</span>(<span class="params">obj</span>)</span><br><span class="line">    // 这里如果你传进来 是数组 那么 就是 <span class="title">Array</span> 对象 就是 <span class="title">Object</span> 如果是函数 就是 <span class="title">Function</span> 如果是 数字 那么就是 <span class="title">Number</span></span><br><span class="line">    // 然后我们进创建一个新实例 可能是新数组 也可能是新对象</span><br><span class="line">    <span class="title">let</span> <span class="title">clone</span> = <span class="title">new</span> <span class="title">constructor</span></span><br><span class="line">    <span class="title">for</span>(<span class="params"><span class="keyword">let</span> key <span class="keyword">in</span> obj</span>)&#123;</span><br><span class="line">        <span class="comment">//只有私有的我们才处理</span></span><br><span class="line">        <span class="keyword">if</span>(!obj.hasOwnProperty(key)) <span class="keyword">break</span></span><br><span class="line">        clone[key] = cloneDeep(obj[key])</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> clone</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="数据类型检测"><a href="#数据类型检测" class="headerlink" title="数据类型检测"></a>数据类型检测</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> <span class="keyword">typeof</span>  返回结果是一个字符串 字符串包含了对应的数据类型 number string boolean bigint <span class="literal">undefined</span> symbol object <span class="function"><span class="keyword">function</span> 原理是 按照计算机底层存储的二进制来进行检测的 也无法区分 是哪个构造函数 搞出来的实例</span></span><br><span class="line"><span class="function"><span class="title">typeof</span> <span class="title">null</span>  -&gt; &#x27;<span class="title">object</span>&#x27;</span></span><br><span class="line"><span class="function">2. <span class="title">instancof</span> 并不是用来检测数据类型 是用来检测当前实例是否属于这个类 不支持基本数据类型值</span></span><br><span class="line"><span class="function">3.<span class="title">constructor</span> 支持基本数里类型值</span></span><br><span class="line"><span class="function">4.<span class="title">Object</span>.<span class="title">prototype</span>.<span class="title">toString</span>.<span class="title">call</span> 专门用来检测数据类型的 (<span class="params">很强大很暴力的一种版本,基本没有缺陷</span>)</span></span><br></pre></td></tr></table></figure>
<h3 id="instancof"><a href="#instancof" class="headerlink" title="instancof"></a>instancof</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//instancof </span></span><br><span class="line"><span class="keyword">let</span> arr = []</span><br><span class="line"><span class="built_in">console</span>.log(arr <span class="keyword">instanceof</span> <span class="built_in">Array</span>) <span class="comment">//true</span></span><br><span class="line"><span class="built_in">console</span>.log(arr <span class="keyword">instanceof</span> <span class="built_in">Object</span>) <span class="comment">//true 绝对不能证明XX instancof Object 是 true 就是普通对象</span></span><br><span class="line"><span class="built_in">console</span>.log(arr <span class="keyword">instanceof</span> <span class="built_in">RegExp</span>) <span class="comment">//false</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 检测字面量方式的时候 会出错</span></span><br><span class="line"><span class="keyword">let</span> n = <span class="number">10</span></span><br><span class="line"><span class="keyword">let</span> m = <span class="keyword">new</span> <span class="built_in">Number</span>(<span class="number">10</span>)</span><br><span class="line"><span class="built_in">console</span>.log(n <span class="keyword">instanceof</span> <span class="built_in">Number</span>) <span class="comment">// false</span></span><br><span class="line"><span class="built_in">console</span>.log(m <span class="keyword">instanceof</span> <span class="built_in">Number</span>) <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果把原型改了 检测的值也会出错</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params"></span>)</span>&#123;&#125;</span><br><span class="line">Person.prototype = <span class="built_in">Array</span>.prototype</span><br><span class="line"><span class="keyword">let</span> p1 = <span class="keyword">new</span> Person</span><br><span class="line"><span class="built_in">console</span>.log(p1 <span class="keyword">instanceof</span> Person) <span class="comment">//输出为true</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 原理 </span></span><br><span class="line">arr instancof <span class="built_in">Array</span> </span><br><span class="line"><span class="comment">//其实相当于调取了 Array 上的一个方法Symbol.hasInstance</span></span><br><span class="line"><span class="built_in">Array</span>[<span class="built_in">Symbol</span>.hasInstance](arr)</span><br><span class="line"><span class="comment">// 而我们知道 Array 是 Function 的实例 所以这个方法 在Funcion的 原型上 prototype</span></span><br><span class="line">arr.__proto__ === <span class="built_in">Array</span>.prototype =&gt; arr <span class="keyword">instanceof</span> <span class="built_in">Array</span></span><br><span class="line">arr.__proto__.__proto__ === <span class="built_in">Object</span>.prototype =&gt; arr <span class="keyword">instanceof</span> <span class="built_in">Object</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//重写 instancof </span></span><br><span class="line"><span class="comment">// obj是要检测的值</span></span><br><span class="line"><span class="comment">// constructor 检测的 是不是 你传进来的</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">instance_of</span>(<span class="params">obj,constructor</span>)</span>&#123;</span><br><span class="line">    <span class="comment">//参数校验 如果你传进来的 不是引用类型 比如是字面量的10 或这 字符串 null 我就直接false</span></span><br><span class="line">    <span class="keyword">if</span>(obj === <span class="literal">null</span> || <span class="regexp">/^(object|function)$/i</span>.test(<span class="keyword">typeof</span> obj)) <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">    <span class="keyword">if</span>(<span class="keyword">typeof</span> <span class="title">constructor</span> !== &#x27;<span class="title">function</span>&#x27;) <span class="title">throw</span> <span class="title">new</span> <span class="title">Error</span>(<span class="params"><span class="string">&#x27;类型错误&#x27;</span></span>)</span><br><span class="line">    //这一步 就是 <span class="title">obj</span> 的原型连  </span><br><span class="line">    <span class="title">let</span> <span class="title">proto</span> = <span class="title">Object</span>.<span class="title">getPrototypeOf</span>(<span class="params">obj</span>)</span><br><span class="line">    //获取 你传进来的函数的原型 </span><br><span class="line">    <span class="title">let</span> <span class="title">prototype</span> = <span class="title">constructor</span>.<span class="title">prototype</span></span><br><span class="line">    //开始循环</span><br><span class="line">    <span class="title">while</span>(<span class="params"><span class="literal">true</span></span>)&#123;</span><br><span class="line">        <span class="comment">// 顺着原型链一层一层向上找 如果找到最后 找到头了 就返回null</span></span><br><span class="line">        <span class="keyword">if</span>(proto === <span class="literal">null</span>) <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">        <span class="comment">// 如果是一个自定义类 我们就返回true</span></span><br><span class="line">        <span class="keyword">if</span>(proto === prototype) <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">        <span class="comment">//以上都没有的就继续一层一层 向上找</span></span><br><span class="line">        proto = <span class="built_in">Object</span>.getPrototypeOf(proto)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="constructor-NaN"><a href="#constructor-NaN" class="headerlink" title="constructor"></a>constructor</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 如果constructor 在不修改的情况下</span></span><br><span class="line"><span class="keyword">let</span> arr = []</span><br><span class="line"><span class="built_in">console</span>.log(arr.constructor === <span class="built_in">Array</span>) <span class="comment">//true</span></span><br><span class="line"><span class="built_in">console</span>.log(arr.constructor === <span class="built_in">Object</span>) <span class="comment">//false</span></span><br><span class="line"><span class="built_in">console</span>.log(arr.constructor === <span class="built_in">RegExp</span>) <span class="comment">//false</span></span><br><span class="line"><span class="comment">// 而且 也支持 基本数据类型值</span></span><br><span class="line"><span class="keyword">let</span> n = <span class="number">10</span></span><br><span class="line">n.construtor === <span class="built_in">Number</span> <span class="comment">// true</span></span><br></pre></td></tr></table></figure>
<h3 id="Object-prototype-toString-call"><a href="#Object-prototype-toString-call" class="headerlink" title="Object.prototype.toString.call"></a>Object.prototype.toString.call</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 基本上所有类的原型上 都有toString方法 Number String Boolean Array Function RegExp Symbol Date Object</span></span><br><span class="line"><span class="comment">// 这些方法里面 除了 object.prototype.toString  是用来转检测数据类型的 其余都是用来转换为字符串的</span></span><br><span class="line">(&#123;&#125;).toString() <span class="comment">// 调取的就是 object.prototype.toString 方法 返回就是它的类型&#x27;[object Object]&#x27;</span></span><br><span class="line"><span class="built_in">document</span>.querySelectorAll(<span class="string">&#x27;*&#x27;</span>).toString() <span class="comment">//调用的也是object.prototype.toString 方法 返回的是 &#x27;[object NodeList]&#x27;</span></span><br><span class="line"><span class="comment">//以上的返回结果  后半段的值 取的是 Symbol.toStringTag这个值</span></span><br><span class="line"><span class="string">&#x27;[object [Symbol.toStringTag]]&#x27;</span></span><br><span class="line"><span class="comment">//所以我们使用的时候</span></span><br><span class="line"><span class="keyword">let</span> arr = []</span><br><span class="line"><span class="comment">//使用这个方法 来检测 arr</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(arr) <span class="comment">//输出 [object Array]</span></span><br></pre></td></tr></table></figure>
</article><div class="post-copyright"><div class="post-copyright__title"><span class="post-copyright-info"><h>面向对象</h></span></div><div class="post-copyright__type"><span class="post-copyright-info"><a href="http://example.com/2019/03/28/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/">http://example.com/2019/03/28/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/</a></span></div><div class="post-copyright-m"><div class="post-copyright-m-info"><div class="post-copyright-a"><h>作者</h><div class="post-copyright-cc-info"><h>北城韩雨</h></div></div><div class="post-copyright-c"><h>发布于</h><div class="post-copyright-cc-info"><h>2019-03-28</h></div></div><div class="post-copyright-u"><h>更新于</h><div class="post-copyright-cc-info"><h>2019-06-03</h></div></div><div class="post-copyright-c"><h>许可协议</h><div class="post-copyright-cc-info"><a class="icon" rel="noopener" target="_blank" title="Creative Commons" href="https://creativecommons.org/"><i class="fab fa-creative-commons"></i></a><a rel="noopener" target="_blank" title="CC BY-NC-SA 4.0" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a></div></div></div></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/JavaScript/">JavaScript</a></div><div class="post_share"></div></div><link rel="stylesheet" href="/" media="defer" onload="this.media='all'"/><div class="post-reward"><button class="tip-button reward-button"><span class="tip-button__text">打赏</span><div class="coin-wrapper"><div class="coin"><div class="coin__middle"></div><div class="coin__back"></div><div class="coin__front"></div></div></div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="/img/weixin.jpg" target="_blank"><img class="post-qr-code-img" src="/img/weixin.jpg" alt="微信"/></a><div class="post-qr-code-desc">微信</div></li><li class="reward-item"><a href="/img/taobao.jpg" target="_blank"><img class="post-qr-code-img" src="/img/taobao.jpg" alt="支付宝"/></a><div class="post-qr-code-desc">支付宝</div></li></ul></div></button></div><script defer="defer" src="/"></script><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2019/03/29/%E5%90%8C%E6%AD%A5%E5%BC%82%E7%BC%96%E7%A8%8B/"><img class="prev-cover" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2018-07-17%2F3eca5394963b50e37b7be2ba320029ec%2F00003.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&amp;refer=http%3A%2F%2Fpic.vjshi.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1629530644&amp;t=10679b5732c52e39eeb588040240a790" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">同步异步编程</div></div></a></div><div class="next-post pull-right"><a href="/2019/03/27/MongoDB%E8%BF%9B%E9%98%B6/"><img class="next-cover" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2017-07-20%2F4f06f9aa2ebcea6691a78537052e8e9f%2F00001.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&amp;refer=http%3A%2F%2Fpic.vjshi.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1629530599&amp;t=32fb97bad7007bdc6c712ccadacd5721" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">MongoDB进阶</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span> 相关推荐</span></div><div class="relatedPosts-list"><div><a href="/2020/04/27/写一个简版的Promise/" title="手写一个简版的promise"><img class="cover" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2017-07-20%2F4f06f9aa2ebcea6691a78537052e8e9f%2F00001.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&refer=http%3A%2F%2Fpic.vjshi.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1629530599&t=32fb97bad7007bdc6c712ccadacd5721" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2020-04-27</div><div class="title">手写一个简版的promise</div></div></a></div><div><a href="/2020/04/27/设计模式/" title="发布订阅"><img class="cover" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fcz-video-photo.oss-cn-beijing.aliyuncs.com%2F20191017%2F4cfc341591d242327b67e9ceb6953612_00002.jpg&refer=http%3A%2F%2Fcz-video-photo.oss-cn-beijing.aliyuncs.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1629530702&t=80943e12d5239f63beafd6d1c540855f" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2020-04-27</div><div class="title">发布订阅</div></div></a></div><div><a href="/2020/04/26/js事件循环机制/" title="JavaScript 事件循环机制"><img class="cover" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2018-07-17%2F3eca5394963b50e37b7be2ba320029ec%2F00003.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&refer=http%3A%2F%2Fpic.vjshi.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1629530644&t=10679b5732c52e39eeb588040240a790" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2020-04-26</div><div class="title">JavaScript 事件循环机制</div></div></a></div><div><a href="/2020/04/22/ES6/" title="ES6/ES7/ES8/ES9/ES10/ES11"><img class="cover" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2018-07-17%2Faf41dabad727ba80c9ca8a2bfbd22a58%2F00004.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&refer=http%3A%2F%2Fpic.vjshi.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1629530659&t=bbcfe1e86f393eecbb0722db1b92e475" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2020-04-22</div><div class="title">ES6/ES7/ES8/ES9/ES10/ES11</div></div></a></div><div><a href="/2020/04/01/事件绑定/" title="事件绑定"><img class="cover" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2018-07-17%2Faf41dabad727ba80c9ca8a2bfbd22a58%2F00004.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&refer=http%3A%2F%2Fpic.vjshi.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1629530659&t=bbcfe1e86f393eecbb0722db1b92e475" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2020-04-01</div><div class="title">事件绑定</div></div></a></div><div><a href="/2020/03/29/Dialog/" title="弹框组件"><img class="cover" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fcz-video-photo.oss-cn-beijing.aliyuncs.com%2F20191017%2F4cfc341591d242327b67e9ceb6953612_00002.jpg&refer=http%3A%2F%2Fcz-video-photo.oss-cn-beijing.aliyuncs.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1629530702&t=80943e12d5239f63beafd6d1c540855f" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2020-03-29</div><div class="title">弹框组件</div></div></a></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="/img/my.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">北城韩雨</div><div class="author-info__description">一个前端界的小学生</div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">65</div></a></div><div class="card-info-data-item is-center"><a href="/tags/"><div class="headline">标签</div><div class="length-num">23</div></a></div><div class="card-info-data-item is-center"><a href="/categories/"><div class="headline">分类</div><div class="length-num">21</div></a></div></div><a class="button--animated" id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/wazer1987"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="/wangzhengvslike@163.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn card-announcement-animation"></i><span>公告</span></div><div class="announcement_content"><p>感谢访问本站，如喜欢请收藏。本站主要分享前端知识，立志成为资深前端工程师，但目前是一个前端界的小学生 若喜欢可以打赏请博主喝一杯冰阔落</p> <p>另外请大家多多支持淼哥的开源项目</p> <p>https://github.com/flipped-aurora/gin-vue-admin</p> <p>🌟🌟欢迎大家start 🌟🌟</p> <p>欢迎加入博主的前端技术交流群</p> <p style="background:rgba(255,255,255,1);margin:0"> <img src="/img/code.png"></img> </p></div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3"><span class="toc-text">编程思想</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%A6%82%E5%BF%B5"><span class="toc-text">面向对象的概念</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB"><span class="toc-text">自定义类</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B8%A6-new-%E7%9A%84%E5%87%BD%E6%95%B0%E6%89%A7%E8%A1%8C%E9%83%BD%E5%B9%B2%E4%BA%86%E4%BB%80%E4%B9%88"><span class="toc-text">带 new 的函数执行都干了什么</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1-%E5%8E%9F%E5%9E%8Bprototype-%E5%92%8C-%E5%8E%9F%E5%9E%8B%E9%93%BEproto"><span class="toc-text">面向对象 原型prototype 和 原型链proto</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8E%9F%E5%9E%8B%E9%87%8D%E5%AE%9A%E5%90%91"><span class="toc-text">原型重定向</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8E%9F%E5%9E%8B%E9%87%8D%E5%86%99-new"><span class="toc-text">原型重写 new</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9F%BA%E4%BA%8E%E5%86%85%E7%BD%AE%E7%B1%BB%E5%8E%9F%E5%9E%8B%E6%89%A9%E5%85%85%E6%96%B9%E6%B3%95"><span class="toc-text">基于内置类原型扩充方法</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%87%BD%E6%95%B0%E7%9A%84%E4%B8%89%E7%A7%8D%E8%A7%92%E8%89%B2"><span class="toc-text">函数的三种角色</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#THIS%E7%A7%8D%E7%9A%84%E4%BA%94%E7%A7%8D%E6%83%85%E5%86%B5"><span class="toc-text">THIS种的五种情况</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99call-apply-bind-%E6%BA%90%E7%A0%81"><span class="toc-text">手写call &#x2F; apply &#x2F; bind 源码</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%89%8B%E5%86%99-bind"><span class="toc-text">手写 bind</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%89%8B%E5%86%99call"><span class="toc-text">手写call</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#js%E4%B8%AD%E7%9A%84%E7%BB%A7%E6%89%BF"><span class="toc-text">js中的继承</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8E%9F%E5%9E%8B%E7%BB%A7%E6%89%BF"><span class="toc-text">原型继承</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#call%E7%BB%A7%E6%89%BF"><span class="toc-text">call继承</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%84%E7%94%9F%E7%BB%84%E5%90%88%E5%BC%8F%E7%BB%A7%E6%89%BF"><span class="toc-text">寄生组合式继承</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%95%B0%E7%BB%84%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%B7%B1%E5%85%8B%E9%9A%86-%E6%B5%85%E5%85%8B%E9%9A%86"><span class="toc-text">数组对象的深克隆&#x2F;浅克隆</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%85%E5%85%8B%E9%9A%86"><span class="toc-text">浅克隆</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B7%B1%E5%85%8B%E9%9A%86"><span class="toc-text">深克隆</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E6%A3%80%E6%B5%8B"><span class="toc-text">数据类型检测</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#instancof"><span class="toc-text">instancof</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#constructor-NaN"><span class="toc-text">constructor</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Object-prototype-toString-call"><span class="toc-text">Object.prototype.toString.call</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2021/04/16/gin-vue-admin/" title="Gin-Vue-Admin"><img src="/img/gin-vue-admin.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Gin-Vue-Admin"/></a><div class="content"><a class="title" href="/2021/04/16/gin-vue-admin/" title="Gin-Vue-Admin">Gin-Vue-Admin</a><time datetime="2021-04-15T16:00:00.000Z" title="发表于 2021-04-16 00:00:00">2021-04-16</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/01/08/Vue%E6%BA%90%E7%A0%81%E5%BC%80%E5%8F%91%E4%B9%8B%E7%BB%84%E4%BB%B6%E7%9A%84%E6%B8%B2%E6%9F%9310/" title="Vue源码开发-组件的渲染10"><img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2018-07-17%2F3eca5394963b50e37b7be2ba320029ec%2F00003.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&amp;refer=http%3A%2F%2Fpic.vjshi.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1629530644&amp;t=10679b5732c52e39eeb588040240a790" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Vue源码开发-组件的渲染10"/></a><div class="content"><a class="title" href="/2021/01/08/Vue%E6%BA%90%E7%A0%81%E5%BC%80%E5%8F%91%E4%B9%8B%E7%BB%84%E4%BB%B6%E7%9A%84%E6%B8%B2%E6%9F%9310/" title="Vue源码开发-组件的渲染10">Vue源码开发-组件的渲染10</a><time datetime="2021-01-07T16:00:00.000Z" title="发表于 2021-01-08 00:00:00">2021-01-08</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/01/07/Vue%E6%BA%90%E7%A0%81%E5%BC%80%E5%8F%91%E4%B9%8B%E7%BB%84%E4%BB%B6%E7%9A%84%E5%90%88%E5%B9%B6%E7%AD%96%E7%95%A509/" title="Vue源码开发-组件合并策略09"><img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fcz-video-photo.oss-cn-beijing.aliyuncs.com%2F20191017%2F4cfc341591d242327b67e9ceb6953612_00002.jpg&amp;refer=http%3A%2F%2Fcz-video-photo.oss-cn-beijing.aliyuncs.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1629530702&amp;t=80943e12d5239f63beafd6d1c540855f" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Vue源码开发-组件合并策略09"/></a><div class="content"><a class="title" href="/2021/01/07/Vue%E6%BA%90%E7%A0%81%E5%BC%80%E5%8F%91%E4%B9%8B%E7%BB%84%E4%BB%B6%E7%9A%84%E5%90%88%E5%B9%B6%E7%AD%96%E7%95%A509/" title="Vue源码开发-组件合并策略09">Vue源码开发-组件合并策略09</a><time datetime="2021-01-06T16:00:00.000Z" title="发表于 2021-01-07 00:00:00">2021-01-07</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/01/06/Vue%E6%BA%90%E7%A0%81%E5%BC%80%E5%8F%91%E4%B9%8B%E6%95%B0%E7%BB%84%E7%9A%84%E4%BE%9D%E8%B5%96%E6%94%B6%E9%9B%8608/" title="Vue源码开发-数组的依赖收集08"><img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2018-07-17%2F3eca5394963b50e37b7be2ba320029ec%2F00003.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&amp;refer=http%3A%2F%2Fpic.vjshi.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1629530644&amp;t=10679b5732c52e39eeb588040240a790" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Vue源码开发-数组的依赖收集08"/></a><div class="content"><a class="title" href="/2021/01/06/Vue%E6%BA%90%E7%A0%81%E5%BC%80%E5%8F%91%E4%B9%8B%E6%95%B0%E7%BB%84%E7%9A%84%E4%BE%9D%E8%B5%96%E6%94%B6%E9%9B%8608/" title="Vue源码开发-数组的依赖收集08">Vue源码开发-数组的依赖收集08</a><time datetime="2021-01-05T16:00:00.000Z" title="发表于 2021-01-06 00:00:00">2021-01-06</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/01/06/Vue%E6%BA%90%E7%A0%81%E5%BC%80%E5%8F%91%E4%B9%8B%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%90%88%E5%B9%B607/" title="Vue源码开发-生命周期合并07"><img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.vjshi.com%2F2018-07-17%2Faf41dabad727ba80c9ca8a2bfbd22a58%2F00004.jpg%3Fx-oss-process%3Dstyle%2Fwatermark&amp;refer=http%3A%2F%2Fpic.vjshi.com&amp;app=2002&amp;size=f9999,10000&amp;q=a80&amp;n=0&amp;g=0n&amp;fmt=jpeg?sec=1629530659&amp;t=bbcfe1e86f393eecbb0722db1b92e475" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Vue源码开发-生命周期合并07"/></a><div class="content"><a class="title" href="/2021/01/06/Vue%E6%BA%90%E7%A0%81%E5%BC%80%E5%8F%91%E4%B9%8B%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%90%88%E5%B9%B607/" title="Vue源码开发-生命周期合并07">Vue源码开发-生命周期合并07</a><time datetime="2021-01-05T16:00:00.000Z" title="发表于 2021-01-06 00:00:00">2021-01-06</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright"><span>&copy;2017 - 2021</span><svg style="width:2em; height:2em;position: relative;top: 10px;" aria-hidden="true"><use xlink:href="#icon-Butterfly"></use></svg><span>北城韩雨</span></div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div><div class="footer_custom_text"><p><a style="margin-inline:5px" target="_blank" href="https://hexo.io/"><img src="https://img.shields.io/badge/Frame-Hexo-blue?style=flat&logo=hexo" title="博客框架为Hexo"></a><a style="margin-inline:5px" target="_blank" href="https://butterfly.js.org/"><img src="https://img.shields.io/badge/Theme-Butterfly-6513df?style=flat&logo=bitdefender" title="主题采用butterfly"></a><a style="margin-inline:5px" target="_blank" href="https://www.jsdelivr.com/"><img src="https://img.shields.io/badge/CDN-jsDelivr-orange?style=flat&logo=jsDelivr" title="本站使用JsDelivr为静态资源提供CDN加速"></a></p></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/medium-zoom/dist/medium-zoom.min.js"></script><div class="js-pjax"></div><script defer src="/live2d-widget/autoload.js"></script><script src="/js/coin.js"></script><script async src="//at.alicdn.com/t/font_2700632_3rtvhzzpl3h.js"></script><script src="/js/liuxing.js" data-pjax></script><canvas class="fireworks" mobile="false"></canvas><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/fireworks.min.js"></script><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/activate-power-mode.min.js"></script><script>POWERMODE.colorful = true;
POWERMODE.shake = true;
POWERMODE.mobile = false;
document.body.addEventListener('input', POWERMODE);
</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><!-- hexo injector body_end start --><div class="js-pjax"><script async="async">var arr = document.getElementsByClassName('recent-post-item');
for(var i = 0;i<arr.length;i++){
    arr[i].classList.add('wow');
    arr[i].classList.add('animate__zoomIn');
    arr[i].setAttribute('data-wow-duration', '1s');
    arr[i].setAttribute('data-wow-delay', '0ms');
    arr[i].setAttribute('data-wow-offset', '100');
    arr[i].setAttribute('data-wow-iteration', '1');
  }</script><script async="async">var arr = document.getElementsByClassName('card-widget');
for(var i = 0;i<arr.length;i++){
    arr[i].classList.add('wow');
    arr[i].classList.add('animate__zoomIn');
    arr[i].setAttribute('data-wow-duration', '');
    arr[i].setAttribute('data-wow-delay', '');
    arr[i].setAttribute('data-wow-offset', '');
    arr[i].setAttribute('data-wow-iteration', '');
  }</script></div><script defer src="https://cdn.jsdelivr.net/gh/graingert/wow@1.3.0/dist/wow.min.js"></script><script defer src="https://cdn.jsdelivr.net/npm/hexo-butterfly-wowjs/lib/wow_init.min.js"></script><script async src="//at.alicdn.com/t/font_2032782_8d5kxvn09md.js"></script><!-- hexo injector body_end end --></body></html>